home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume22 / gawk2.11 / part12 < prev    next >
Encoding:
Internet Message Format  |  1990-06-07  |  53.8 KB

  1. Subject:  v22i098:  GNU AWK, version 2.11, Part12/16
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 1c391d97 561291f7 b72d5e58 3217729b
  5.  
  6. Submitted-by: "Arnold D. Robbins" <arnold@unix.cc.emory.edu>
  7. Posting-number: Volume 22, Issue 98
  8. Archive-name: gawk2.11/part12
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then feed it
  12. # into a shell via "sh file" or similar.  To overwrite existing files,
  13. # type "sh file -c".
  14. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  15. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  16. # Contents:  ./builtin.c ./eval.c ./missing.d/gcvt.c
  17. # Wrapped by rsalz@litchi.bbn.com on Wed Jun  6 12:24:57 1990
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. echo If this archive is complete, you will see the following message:
  20. echo '          "shar: End of archive 12 (of 16)."'
  21. if test -f './builtin.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'./builtin.c'\"
  23. else
  24.   echo shar: Extracting \"'./builtin.c'\" \(20659 characters\)
  25.   sed "s/^X//" >'./builtin.c' <<'END_OF_FILE'
  26. X/*
  27. X * builtin.c - Builtin functions and various utility procedures 
  28. X */
  29. X
  30. X/* 
  31. X * Copyright (C) 1986, 1988, 1989 the Free Software Foundation, Inc.
  32. X * 
  33. X * This file is part of GAWK, the GNU implementation of the
  34. X * AWK Progamming Language.
  35. X * 
  36. X * GAWK is free software; you can redistribute it and/or modify
  37. X * it under the terms of the GNU General Public License as published by
  38. X * the Free Software Foundation; either version 1, or (at your option)
  39. X * any later version.
  40. X * 
  41. X * GAWK is distributed in the hope that it will be useful,
  42. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  43. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  44. X * GNU General Public License for more details.
  45. X * 
  46. X * You should have received a copy of the GNU General Public License
  47. X * along with GAWK; see the file COPYING.  If not, write to
  48. X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  49. X */
  50. X
  51. X#include "awk.h"
  52. X
  53. Xextern void srandom();
  54. Xextern char *initstate();
  55. Xextern char *setstate();
  56. Xextern long random();
  57. X
  58. Xextern NODE **fields_arr;
  59. X
  60. Xstatic void get_one();
  61. Xstatic void get_two();
  62. Xstatic int get_three();
  63. X
  64. X/* Builtin functions */
  65. XNODE *
  66. Xdo_exp(tree)
  67. XNODE *tree;
  68. X{
  69. X    NODE *tmp;
  70. X    double d, res;
  71. X    double exp();
  72. X
  73. X    get_one(tree, &tmp);
  74. X    d = force_number(tmp);
  75. X    free_temp(tmp);
  76. X    errno = 0;
  77. X    res = exp(d);
  78. X    if (errno == ERANGE)
  79. X        warning("exp argument %g is out of range", d);
  80. X    return tmp_number((AWKNUM) res);
  81. X}
  82. X
  83. XNODE *
  84. Xdo_index(tree)
  85. XNODE *tree;
  86. X{
  87. X    NODE *s1, *s2;
  88. X    register char *p1, *p2;
  89. X    register int l1, l2;
  90. X    long ret;
  91. X
  92. X
  93. X    get_two(tree, &s1, &s2);
  94. X    force_string(s1);
  95. X    force_string(s2);
  96. X    p1 = s1->stptr;
  97. X    p2 = s2->stptr;
  98. X    l1 = s1->stlen;
  99. X    l2 = s2->stlen;
  100. X    ret = 0;
  101. X    if (! strict && IGNORECASE_node->var_value->numbr != 0.0) {
  102. X        while (l1) {
  103. X            if (casetable[*p1] == casetable[*p2]
  104. X                && strncasecmp(p1, p2, l2) == 0) {
  105. X                ret = 1 + s1->stlen - l1;
  106. X                break;
  107. X            }
  108. X            l1--;
  109. X            p1++;
  110. X        }
  111. X    } else {
  112. X        while (l1) {
  113. X            if (STREQN(p1, p2, l2)) {
  114. X                ret = 1 + s1->stlen - l1;
  115. X                break;
  116. X            }
  117. X            l1--;
  118. X            p1++;
  119. X        }
  120. X    }
  121. X    free_temp(s1);
  122. X    free_temp(s2);
  123. X    return tmp_number((AWKNUM) ret);
  124. X}
  125. X
  126. XNODE *
  127. Xdo_int(tree)
  128. XNODE *tree;
  129. X{
  130. X    NODE *tmp;
  131. X    double floor();
  132. X    double d;
  133. X
  134. X    get_one(tree, &tmp);
  135. X    d = floor((double)force_number(tmp));
  136. X    free_temp(tmp);
  137. X    return tmp_number((AWKNUM) d);
  138. X}
  139. X
  140. XNODE *
  141. Xdo_length(tree)
  142. XNODE *tree;
  143. X{
  144. X    NODE *tmp;
  145. X    int len;
  146. X
  147. X    get_one(tree, &tmp);
  148. X    len = force_string(tmp)->stlen;
  149. X    free_temp(tmp);
  150. X    return tmp_number((AWKNUM) len);
  151. X}
  152. X
  153. XNODE *
  154. Xdo_log(tree)
  155. XNODE *tree;
  156. X{
  157. X    NODE *tmp;
  158. X    double log();
  159. X    double d, arg;
  160. X
  161. X    get_one(tree, &tmp);
  162. X    arg = (double) force_number(tmp);
  163. X    if (arg < 0.0)
  164. X        warning("log called with negative argument %g", arg);
  165. X    d = log(arg);
  166. X    free_temp(tmp);
  167. X    return tmp_number((AWKNUM) d);
  168. X}
  169. X
  170. X/*
  171. X * Note that the output buffer cannot be static because sprintf may get
  172. X * called recursively by force_string.  Hence the wasteful alloca calls 
  173. X */
  174. X
  175. X/* %e and %f formats are not properly implemented.  Someone should fix them */
  176. XNODE *
  177. Xdo_sprintf(tree)
  178. XNODE *tree;
  179. X{
  180. X#define bchunk(s,l) if(l) {\
  181. X    while((l)>ofre) {\
  182. X      char *tmp;\
  183. X      tmp=(char *)alloca(osiz*2);\
  184. X      memcpy(tmp,obuf,olen);\
  185. X      obuf=tmp;\
  186. X      ofre+=osiz;\
  187. X      osiz*=2;\
  188. X    }\
  189. X    memcpy(obuf+olen,s,(l));\
  190. X    olen+=(l);\
  191. X    ofre-=(l);\
  192. X  }
  193. X
  194. X    /* Is there space for something L big in the buffer? */
  195. X#define chksize(l)  if((l)>ofre) {\
  196. X    char *tmp;\
  197. X    tmp=(char *)alloca(osiz*2);\
  198. X    memcpy(tmp,obuf,olen);\
  199. X    obuf=tmp;\
  200. X    ofre+=osiz;\
  201. X    osiz*=2;\
  202. X  }
  203. X
  204. X    /*
  205. X     * Get the next arg to be formatted.  If we've run out of args,
  206. X     * return "" (Null string) 
  207. X     */
  208. X#define parse_next_arg() {\
  209. X  if(!carg) arg= Nnull_string;\
  210. X  else {\
  211. X      get_one(carg,&arg);\
  212. X    carg=carg->rnode;\
  213. X  }\
  214. X }
  215. X
  216. X    char *obuf;
  217. X    int osiz, ofre, olen;
  218. X    static char chbuf[] = "0123456789abcdef";
  219. X    static char sp[] = " ";
  220. X    char *s0, *s1;
  221. X    int n0;
  222. X    NODE *sfmt, *arg;
  223. X    register NODE *carg;
  224. X    long fw, prec, lj, alt, big;
  225. X    long *cur;
  226. X    long val;
  227. X#ifdef sun386            /* Can't cast unsigned (int/long) from ptr->value */
  228. X    long tmp_uval;        /* on 386i 4.0.1 C compiler -- it just hangs */
  229. X#endif
  230. X    unsigned long uval;
  231. X    int sgn;
  232. X    int base;
  233. X    char cpbuf[30];        /* if we have numbers bigger than 30 */
  234. X    char *cend = &cpbuf[30];/* chars, we lose, but seems unlikely */
  235. X    char *cp;
  236. X    char *fill;
  237. X    double tmpval;
  238. X    char *pr_str;
  239. X    int ucasehex = 0;
  240. X    extern char *gcvt();
  241. X
  242. X
  243. X    obuf = (char *) alloca(120);
  244. X    osiz = 120;
  245. X    ofre = osiz;
  246. X    olen = 0;
  247. X    get_one(tree, &sfmt);
  248. X    sfmt = force_string(sfmt);
  249. X    carg = tree->rnode;
  250. X    for (s0 = s1 = sfmt->stptr, n0 = sfmt->stlen; n0-- > 0;) {
  251. X        if (*s1 != '%') {
  252. X            s1++;
  253. X            continue;
  254. X        }
  255. X        bchunk(s0, s1 - s0);
  256. X        s0 = s1;
  257. X        cur = &fw;
  258. X        fw = 0;
  259. X        prec = 0;
  260. X        lj = alt = big = 0;
  261. X        fill = sp;
  262. X        cp = cend;
  263. X        s1++;
  264. X
  265. Xretry:
  266. X        --n0;
  267. X        switch (*s1++) {
  268. X        case '%':
  269. X            bchunk("%", 1);
  270. X            s0 = s1;
  271. X            break;
  272. X
  273. X        case '0':
  274. X            if (fill != sp || lj)
  275. X                goto lose;
  276. X            if (cur == &fw)
  277. X                fill = "0";    /* FALL through */
  278. X        case '1':
  279. X        case '2':
  280. X        case '3':
  281. X        case '4':
  282. X        case '5':
  283. X        case '6':
  284. X        case '7':
  285. X        case '8':
  286. X        case '9':
  287. X            if (cur == 0)
  288. X                goto lose;
  289. X            *cur = s1[-1] - '0';
  290. X            while (n0 > 0 && *s1 >= '0' && *s1 <= '9') {
  291. X                --n0;
  292. X                *cur = *cur * 10 + *s1++ - '0';
  293. X            }
  294. X            goto retry;
  295. X#ifdef not_yet
  296. X        case ' ':        /* print ' ' or '-' */
  297. X        case '+':        /* print '+' or '-' */
  298. X#endif
  299. X        case '-':
  300. X            if (lj || fill != sp)
  301. X                goto lose;
  302. X            lj++;
  303. X            goto retry;
  304. X        case '.':
  305. X            if (cur != &fw)
  306. X                goto lose;
  307. X            cur = ≺
  308. X            goto retry;
  309. X        case '#':
  310. X            if (alt)
  311. X                goto lose;
  312. X            alt++;
  313. X            goto retry;
  314. X        case 'l':
  315. X            if (big)
  316. X                goto lose;
  317. X            big++;
  318. X            goto retry;
  319. X        case 'c':
  320. X            parse_next_arg();
  321. X            if (arg->flags & NUMERIC) {
  322. X#ifdef sun386
  323. X                tmp_uval = arg->numbr; 
  324. X                uval= (unsigned long) tmp_uval;
  325. X#else
  326. X                uval = (unsigned long) arg->numbr;
  327. X#endif
  328. X                cpbuf[0] = uval;
  329. X                prec = 1;
  330. X                pr_str = cpbuf;
  331. X                goto dopr_string;
  332. X            }
  333. X            if (! prec)
  334. X                prec = 1;
  335. X            else if (prec > arg->stlen)
  336. X                prec = arg->stlen;
  337. X            pr_str = arg->stptr;
  338. X            goto dopr_string;
  339. X        case 's':
  340. X            parse_next_arg();
  341. X            arg = force_string(arg);
  342. X            if (!prec || prec > arg->stlen)
  343. X                prec = arg->stlen;
  344. X            pr_str = arg->stptr;
  345. X
  346. X    dopr_string:
  347. X            if (fw > prec && !lj) {
  348. X                while (fw > prec) {
  349. X                    bchunk(sp, 1);
  350. X                    fw--;
  351. X                }
  352. X            }
  353. X            bchunk(pr_str, (int) prec);
  354. X            if (fw > prec) {
  355. X                while (fw > prec) {
  356. X                    bchunk(sp, 1);
  357. X                    fw--;
  358. X                }
  359. X            }
  360. X            s0 = s1;
  361. X            free_temp(arg);
  362. X            break;
  363. X        case 'd':
  364. X        case 'i':
  365. X            parse_next_arg();
  366. X            val = (long) force_number(arg);
  367. X            free_temp(arg);
  368. X            if (val < 0) {
  369. X                sgn = 1;
  370. X                val = -val;
  371. X            } else
  372. X                sgn = 0;
  373. X            do {
  374. X                *--cp = '0' + val % 10;
  375. X                val /= 10;
  376. X            } while (val);
  377. X            if (sgn)
  378. X                *--cp = '-';
  379. X            if (prec > fw)
  380. X                fw = prec;
  381. X            prec = cend - cp;
  382. X            if (fw > prec && !lj) {
  383. X                if (fill != sp && *cp == '-') {
  384. X                    bchunk(cp, 1);
  385. X                    cp++;
  386. X                    prec--;
  387. X                    fw--;
  388. X                }
  389. X                while (fw > prec) {
  390. X                    bchunk(fill, 1);
  391. X                    fw--;
  392. X                }
  393. X            }
  394. X            bchunk(cp, (int) prec);
  395. X            if (fw > prec) {
  396. X                while (fw > prec) {
  397. X                    bchunk(fill, 1);
  398. X                    fw--;
  399. X                }
  400. X            }
  401. X            s0 = s1;
  402. X            break;
  403. X        case 'u':
  404. X            base = 10;
  405. X            goto pr_unsigned;
  406. X        case 'o':
  407. X            base = 8;
  408. X            goto pr_unsigned;
  409. X        case 'X':
  410. X            ucasehex = 1;
  411. X        case 'x':
  412. X            base = 16;
  413. X            goto pr_unsigned;
  414. X    pr_unsigned:
  415. X            parse_next_arg();
  416. X            uval = (unsigned long) force_number(arg);
  417. X            free_temp(arg);
  418. X            do {
  419. X                *--cp = chbuf[uval % base];
  420. X                if (ucasehex && isalpha(*cp))
  421. X                    *cp = toupper(*cp);
  422. X                uval /= base;
  423. X            } while (uval);
  424. X            if (alt && (base == 8 || base == 16)) {
  425. X                if (base == 16) {
  426. X                    if (ucasehex)
  427. X                        *--cp = 'X';
  428. X                    else
  429. X                        *--cp = 'x';
  430. X                }
  431. X                *--cp = '0';
  432. X            }
  433. X            prec = cend - cp;
  434. X            if (fw > prec && !lj) {
  435. X                while (fw > prec) {
  436. X                    bchunk(fill, 1);
  437. X                    fw--;
  438. X                }
  439. X            }
  440. X            bchunk(cp, (int) prec);
  441. X            if (fw > prec) {
  442. X                while (fw > prec) {
  443. X                    bchunk(fill, 1);
  444. X                    fw--;
  445. X                }
  446. X            }
  447. X            s0 = s1;
  448. X            break;
  449. X        case 'g':
  450. X            parse_next_arg();
  451. X            tmpval = force_number(arg);
  452. X            free_temp(arg);
  453. X            if (prec == 0)
  454. X                prec = 13;
  455. X            (void) gcvt(tmpval, (int) prec, cpbuf);
  456. X            prec = strlen(cpbuf);
  457. X            cp = cpbuf;
  458. X            if (fw > prec && !lj) {
  459. X                if (fill != sp && *cp == '-') {
  460. X                    bchunk(cp, 1);
  461. X                    cp++;
  462. X                    prec--;
  463. X                }    /* Deal with .5 as 0.5 */
  464. X                if (fill == sp && *cp == '.') {
  465. X                    --fw;
  466. X                    while (--fw >= prec) {
  467. X                        bchunk(fill, 1);
  468. X                    }
  469. X                    bchunk("0", 1);
  470. X                } else
  471. X                    while (fw-- > prec)
  472. X                        bchunk(fill, 1);
  473. X            } else {/* Turn .5 into 0.5 */
  474. X                /* FOO */
  475. X                if (*cp == '.' && fill == sp) {
  476. X                    bchunk("0", 1);
  477. X                    --fw;
  478. X                }
  479. X            }
  480. X            bchunk(cp, (int) prec);
  481. X            if (fw > prec)
  482. X                while (fw-- > prec)
  483. X                    bchunk(fill, 1);
  484. X            s0 = s1;
  485. X            break;
  486. X        case 'f':
  487. X            parse_next_arg();
  488. X            tmpval = force_number(arg);
  489. X            free_temp(arg);
  490. X            chksize(fw + prec + 5);    /* 5==slop */
  491. X
  492. X            cp = cpbuf;
  493. X            *cp++ = '%';
  494. X            if (lj)
  495. X                *cp++ = '-';
  496. X            if (fill != sp)
  497. X                *cp++ = '0';
  498. X            if (cur != &fw) {
  499. X                (void) strcpy(cp, "*.*f");
  500. X                (void) sprintf(obuf + olen, cpbuf, (int) fw, (int) prec, (double) tmpval);
  501. X            } else {
  502. X                (void) strcpy(cp, "*f");
  503. X                (void) sprintf(obuf + olen, cpbuf, (int) fw, (double) tmpval);
  504. X            }
  505. X            ofre -= strlen(obuf + olen);
  506. X            olen += strlen(obuf + olen);    /* There may be nulls */
  507. X            s0 = s1;
  508. X            break;
  509. X        case 'e':
  510. X            parse_next_arg();
  511. X            tmpval = force_number(arg);
  512. X            free_temp(arg);
  513. X            chksize(fw + prec + 5);    /* 5==slop */
  514. X            cp = cpbuf;
  515. X            *cp++ = '%';
  516. X            if (lj)
  517. X                *cp++ = '-';
  518. X            if (fill != sp)
  519. X                *cp++ = '0';
  520. X            if (cur != &fw) {
  521. X                (void) strcpy(cp, "*.*e");
  522. X                (void) sprintf(obuf + olen, cpbuf, (int) fw, (int) prec, (double) tmpval);
  523. X            } else {
  524. X                (void) strcpy(cp, "*e");
  525. X                (void) sprintf(obuf + olen, cpbuf, (int) fw, (double) tmpval);
  526. X            }
  527. X            ofre -= strlen(obuf + olen);
  528. X            olen += strlen(obuf + olen);    /* There may be nulls */
  529. X            s0 = s1;
  530. X            break;
  531. X
  532. X        default:
  533. X    lose:
  534. X            break;
  535. X        }
  536. X    }
  537. X    bchunk(s0, s1 - s0);
  538. X    free_temp(sfmt);
  539. X    return tmp_string(obuf, olen);
  540. X}
  541. X
  542. Xvoid
  543. Xdo_printf(tree)
  544. XNODE *tree;
  545. X{
  546. X    struct redirect *rp = NULL;
  547. X    register FILE *fp = stdout;
  548. X    int errflg = 0;        /* not used, sigh */
  549. X
  550. X    if (tree->rnode) {
  551. X        rp = redirect(tree->rnode, &errflg);
  552. X        if (rp)
  553. X            fp = rp->fp;
  554. X    }
  555. X    if (fp)
  556. X        print_simple(do_sprintf(tree->lnode), fp);
  557. X    if (rp && (rp->flag & RED_NOBUF))
  558. X        fflush(fp);
  559. X}
  560. X
  561. XNODE *
  562. Xdo_sqrt(tree)
  563. XNODE *tree;
  564. X{
  565. X    NODE *tmp;
  566. X    double sqrt();
  567. X    double d, arg;
  568. X
  569. X    get_one(tree, &tmp);
  570. X    arg = (double) force_number(tmp);
  571. X    if (arg < 0.0)
  572. X        warning("sqrt called with negative argument %g", arg);
  573. X    d = sqrt(arg);
  574. X    free_temp(tmp);
  575. X    return tmp_number((AWKNUM) d);
  576. X}
  577. X
  578. XNODE *
  579. Xdo_substr(tree)
  580. XNODE *tree;
  581. X{
  582. X    NODE *t1, *t2, *t3;
  583. X    NODE *r;
  584. X    register int indx, length;
  585. X
  586. X    t1 = t2 = t3 = NULL;
  587. X    length = -1;
  588. X    if (get_three(tree, &t1, &t2, &t3) == 3)
  589. X        length = (int) force_number(t3);
  590. X    indx = (int) force_number(t2) - 1;
  591. X    t1 = force_string(t1);
  592. X    if (length == -1)
  593. X        length = t1->stlen;
  594. X    if (indx < 0)
  595. X        indx = 0;
  596. X    if (indx >= t1->stlen || length <= 0) {
  597. X        if (t3)
  598. X            free_temp(t3);
  599. X        free_temp(t2);
  600. X        free_temp(t1);
  601. X        return Nnull_string;
  602. X    }
  603. X    if (indx + length > t1->stlen)
  604. X        length = t1->stlen - indx;
  605. X    if (t3)
  606. X        free_temp(t3);
  607. X    free_temp(t2);
  608. X    r =  tmp_string(t1->stptr + indx, length);
  609. X    free_temp(t1);
  610. X    return r;
  611. X}
  612. X
  613. XNODE *
  614. Xdo_system(tree)
  615. XNODE *tree;
  616. X{
  617. X#if defined(unix) || defined(MSDOS) /* || defined(gnu) */
  618. X    NODE *tmp;
  619. X    int ret;
  620. X
  621. X    (void) flush_io ();    /* so output is synchronous with gawk's */
  622. X    get_one(tree, &tmp);
  623. X    ret = system(force_string(tmp)->stptr);
  624. X    ret = (ret >> 8) & 0xff;
  625. X    free_temp(tmp);
  626. X    return tmp_number((AWKNUM) ret);
  627. X#else
  628. X    fatal("the \"system\" function is not supported.");
  629. X    /* NOTREACHED */
  630. X#endif
  631. X}
  632. X
  633. Xvoid 
  634. Xdo_print(tree)
  635. Xregister NODE *tree;
  636. X{
  637. X    struct redirect *rp = NULL;
  638. X    register FILE *fp = stdout;
  639. X    int errflg = 0;        /* not used, sigh */
  640. X
  641. X    if (tree->rnode) {
  642. X        rp = redirect(tree->rnode, &errflg);
  643. X        if (rp)
  644. X            fp = rp->fp;
  645. X    }
  646. X    if (!fp)
  647. X        return;
  648. X    tree = tree->lnode;
  649. X    if (!tree)
  650. X        tree = WHOLELINE;
  651. X    if (tree->type != Node_expression_list) {
  652. X        if (!(tree->flags & STR))
  653. X            cant_happen();
  654. X        print_simple(tree, fp);
  655. X    } else {
  656. X        while (tree) {
  657. X            print_simple(force_string(tree_eval(tree->lnode)), fp);
  658. X            tree = tree->rnode;
  659. X            if (tree)
  660. X                print_simple(OFS_node->var_value, fp);
  661. X        }
  662. X    }
  663. X    print_simple(ORS_node->var_value, fp);
  664. X    if (rp && (rp->flag & RED_NOBUF))
  665. X        fflush(fp);
  666. X}
  667. X
  668. XNODE *
  669. Xdo_tolower(tree)
  670. XNODE *tree;
  671. X{
  672. X    NODE *t1, *t2;
  673. X    register char *cp, *cp2;
  674. X
  675. X    get_one(tree, &t1);
  676. X    t1 = force_string(t1);
  677. X    t2 = tmp_string(t1->stptr, t1->stlen);
  678. X    for (cp = t2->stptr, cp2 = t2->stptr + t2->stlen; cp < cp2; cp++)
  679. X        if (isupper(*cp))
  680. X            *cp = tolower(*cp);
  681. X    free_temp(t1);
  682. X    return t2;
  683. X}
  684. X
  685. XNODE *
  686. Xdo_toupper(tree)
  687. XNODE *tree;
  688. X{
  689. X    NODE *t1, *t2;
  690. X    register char *cp;
  691. X
  692. X    get_one(tree, &t1);
  693. X    t1 = force_string(t1);
  694. X    t2 = tmp_string(t1->stptr, t1->stlen);
  695. X    for (cp = t2->stptr; cp < t2->stptr + t2->stlen; cp++)
  696. X        if (islower(*cp))
  697. X            *cp = toupper(*cp);
  698. X    free_temp(t1);
  699. X    return t2;
  700. X}
  701. X
  702. X/*
  703. X * Get the arguments to functions.  No function cares if you give it too many
  704. X * args (they're ignored).  Only a few fuctions complain about being given
  705. X * too few args.  The rest have defaults.
  706. X */
  707. X
  708. Xstatic void
  709. Xget_one(tree, res)
  710. XNODE *tree, **res;
  711. X{
  712. X    if (!tree) {
  713. X        *res = WHOLELINE;
  714. X        return;
  715. X    }
  716. X    *res = tree_eval(tree->lnode);
  717. X}
  718. X
  719. Xstatic void
  720. Xget_two(tree, res1, res2)
  721. XNODE *tree, **res1, **res2;
  722. X{
  723. X    if (!tree) {
  724. X        *res1 = WHOLELINE;
  725. X        return;
  726. X    }
  727. X    *res1 = tree_eval(tree->lnode);
  728. X    if (!tree->rnode)
  729. X        return;
  730. X    tree = tree->rnode;
  731. X    *res2 = tree_eval(tree->lnode);
  732. X}
  733. X
  734. Xstatic int
  735. Xget_three(tree, res1, res2, res3)
  736. XNODE *tree, **res1, **res2, **res3;
  737. X{
  738. X    if (!tree) {
  739. X        *res1 = WHOLELINE;
  740. X        return 0;
  741. X    }
  742. X    *res1 = tree_eval(tree->lnode);
  743. X    if (!tree->rnode)
  744. X        return 1;
  745. X    tree = tree->rnode;
  746. X    *res2 = tree_eval(tree->lnode);
  747. X    if (!tree->rnode)
  748. X        return 2;
  749. X    tree = tree->rnode;
  750. X    *res3 = tree_eval(tree->lnode);
  751. X    return 3;
  752. X}
  753. X
  754. Xint
  755. Xa_get_three(tree, res1, res2, res3)
  756. XNODE *tree, **res1, **res2, **res3;
  757. X{
  758. X    if (!tree) {
  759. X        *res1 = WHOLELINE;
  760. X        return 0;
  761. X    }
  762. X    *res1 = tree_eval(tree->lnode);
  763. X    if (!tree->rnode)
  764. X        return 1;
  765. X    tree = tree->rnode;
  766. X    *res2 = tree->lnode;
  767. X    if (!tree->rnode)
  768. X        return 2;
  769. X    tree = tree->rnode;
  770. X    *res3 = tree_eval(tree->lnode);
  771. X    return 3;
  772. X}
  773. X
  774. Xvoid
  775. Xprint_simple(tree, fp)
  776. XNODE *tree;
  777. XFILE *fp;
  778. X{
  779. X    if (fwrite(tree->stptr, sizeof(char), tree->stlen, fp) != tree->stlen)
  780. X        warning("fwrite: %s", strerror(errno));
  781. X    free_temp(tree);
  782. X}
  783. X
  784. XNODE *
  785. Xdo_atan2(tree)
  786. XNODE *tree;
  787. X{
  788. X    NODE *t1, *t2;
  789. X    extern double atan2();
  790. X    double d1, d2;
  791. X
  792. X    get_two(tree, &t1, &t2);
  793. X    d1 = force_number(t1);
  794. X    d2 = force_number(t2);
  795. X    free_temp(t1);
  796. X    free_temp(t2);
  797. X    return tmp_number((AWKNUM) atan2(d1, d2));
  798. X}
  799. X
  800. XNODE *
  801. Xdo_sin(tree)
  802. XNODE *tree;
  803. X{
  804. X    NODE *tmp;
  805. X    extern double sin();
  806. X    double d;
  807. X
  808. X    get_one(tree, &tmp);
  809. X    d = sin((double)force_number(tmp));
  810. X    free_temp(tmp);
  811. X    return tmp_number((AWKNUM) d);
  812. X}
  813. X
  814. XNODE *
  815. Xdo_cos(tree)
  816. XNODE *tree;
  817. X{
  818. X    NODE *tmp;
  819. X    extern double cos();
  820. X    double d;
  821. X
  822. X    get_one(tree, &tmp);
  823. X    d = cos((double)force_number(tmp));
  824. X    free_temp(tmp);
  825. X    return tmp_number((AWKNUM) d);
  826. X}
  827. X
  828. Xstatic int firstrand = 1;
  829. Xstatic char state[256];
  830. X
  831. X#define    MAXLONG    2147483647    /* maximum value for long int */
  832. X
  833. X/* ARGSUSED */
  834. XNODE *
  835. Xdo_rand(tree)
  836. XNODE *tree;
  837. X{
  838. X    if (firstrand) {
  839. X        (void) initstate((unsigned) 1, state, sizeof state);
  840. X        srandom(1);
  841. X        firstrand = 0;
  842. X    }
  843. X    return tmp_number((AWKNUM) random() / MAXLONG);
  844. X}
  845. X
  846. XNODE *
  847. Xdo_srand(tree)
  848. XNODE *tree;
  849. X{
  850. X    NODE *tmp;
  851. X    static long save_seed = 1;
  852. X    long ret = save_seed;    /* SVR4 awk srand returns previous seed */
  853. X    extern long time();
  854. X
  855. X    if (firstrand)
  856. X        (void) initstate((unsigned) 1, state, sizeof state);
  857. X    else
  858. X        (void) setstate(state);
  859. X
  860. X    if (!tree)
  861. X        srandom((int) (save_seed = time((long *) 0)));
  862. X    else {
  863. X        get_one(tree, &tmp);
  864. X        srandom((int) (save_seed = (long) force_number(tmp)));
  865. X        free_temp(tmp);
  866. X    }
  867. X    firstrand = 0;
  868. X    return tmp_number((AWKNUM) ret);
  869. X}
  870. X
  871. XNODE *
  872. Xdo_match(tree)
  873. XNODE *tree;
  874. X{
  875. X    NODE *t1;
  876. X    int rstart;
  877. X    struct re_registers reregs;
  878. X    struct re_pattern_buffer *rp;
  879. X    int need_to_free = 0;
  880. X
  881. X    t1 = force_string(tree_eval(tree->lnode));
  882. X    tree = tree->rnode;
  883. X    if (tree == NULL || tree->lnode == NULL)
  884. X        fatal("match called with only one argument");
  885. X    tree = tree->lnode;
  886. X    if (tree->type == Node_regex) {
  887. X        rp = tree->rereg;
  888. X        if (!strict && ((IGNORECASE_node->var_value->numbr != 0)
  889. X            ^ (tree->re_case != 0))) {
  890. X            /* recompile since case sensitivity differs */
  891. X            rp = tree->rereg =
  892. X                mk_re_parse(tree->re_text,
  893. X                (IGNORECASE_node->var_value->numbr != 0));
  894. X            tree->re_case =
  895. X                (IGNORECASE_node->var_value->numbr != 0);
  896. X        }
  897. X    } else {
  898. X        need_to_free = 1;
  899. X        rp = make_regexp(force_string(tree_eval(tree)),
  900. X                (IGNORECASE_node->var_value->numbr != 0));
  901. X        if (rp == NULL)
  902. X            cant_happen();
  903. X    }
  904. X    rstart = re_search(rp, t1->stptr, t1->stlen, 0, t1->stlen, &reregs);
  905. X    free_temp(t1);
  906. X    if (rstart >= 0) {
  907. X        rstart++;    /* 1-based indexing */
  908. X        /* RSTART set to rstart below */
  909. X        RLENGTH_node->var_value->numbr =
  910. X            (AWKNUM) (reregs.end[0] - reregs.start[0]);
  911. X    } else {
  912. X        /*
  913. X         * Match failed. Set RSTART to 0, RLENGTH to -1.
  914. X         * Return the value of RSTART.
  915. X         */
  916. X        rstart = 0;    /* used as return value */
  917. X        RLENGTH_node->var_value->numbr = -1.0;
  918. X    }
  919. X    RSTART_node->var_value->numbr = (AWKNUM) rstart;
  920. X    if (need_to_free) {
  921. X        free(rp->buffer);
  922. X        free(rp->fastmap);
  923. X        free((char *) rp);
  924. X    }
  925. X    return tmp_number((AWKNUM) rstart);
  926. X}
  927. X
  928. Xstatic NODE *
  929. Xsub_common(tree, global)
  930. XNODE *tree;
  931. Xint global;
  932. X{
  933. X    register int len;
  934. X    register char *scan;
  935. X    register char *bp, *cp;
  936. X    int search_start = 0;
  937. X    int match_length;
  938. X    int matches = 0;
  939. X    char *buf;
  940. X    struct re_pattern_buffer *rp;
  941. X    NODE *s;        /* subst. pattern */
  942. X    NODE *t;        /* string to make sub. in; $0 if none given */
  943. X    struct re_registers reregs;
  944. X    unsigned int saveflags;
  945. X    NODE *tmp;
  946. X    NODE **lhs;
  947. X    char *lastbuf;
  948. X    int need_to_free = 0;
  949. X
  950. X    if (tree == NULL)
  951. X        fatal("sub or gsub called with 0 arguments");
  952. X    tmp = tree->lnode;
  953. X    if (tmp->type == Node_regex) {
  954. X        rp = tmp->rereg;
  955. X        if (! strict && ((IGNORECASE_node->var_value->numbr != 0)
  956. X            ^ (tmp->re_case != 0))) {
  957. X            /* recompile since case sensitivity differs */
  958. X            rp = tmp->rereg =
  959. X                mk_re_parse(tmp->re_text,
  960. X                (IGNORECASE_node->var_value->numbr != 0));
  961. X            tmp->re_case = (IGNORECASE_node->var_value->numbr != 0);
  962. X        }
  963. X    } else {
  964. X        need_to_free = 1;
  965. X        rp = make_regexp(force_string(tree_eval(tmp)),
  966. X                (IGNORECASE_node->var_value->numbr != 0));
  967. X        if (rp == NULL)
  968. X            cant_happen();
  969. X    }
  970. X    tree = tree->rnode;
  971. X    if (tree == NULL)
  972. X        fatal("sub or gsub called with only 1 argument");
  973. X    s = force_string(tree_eval(tree->lnode));
  974. X    tree = tree->rnode;
  975. X    deref = 0;
  976. X    field_num = -1;
  977. X    if (tree == NULL) {
  978. X        t = node0_valid ? fields_arr[0] : *get_field(0, 0);
  979. X        lhs = &fields_arr[0];
  980. X        field_num = 0;
  981. X        deref = t;
  982. X    } else {
  983. X        t = tree->lnode;
  984. X        lhs = get_lhs(t, 1);
  985. X        t = force_string(tree_eval(t));
  986. X    }
  987. X    /*
  988. X     * create a private copy of the string
  989. X     */
  990. X    if (t->stref > 1 || (t->flags & PERM)) {
  991. X        saveflags = t->flags;
  992. X        t->flags &= ~MALLOC;
  993. X        tmp = dupnode(t);
  994. X        t->flags = saveflags;
  995. X        do_deref();
  996. X        t = tmp;
  997. X        if (lhs)
  998. X            *lhs = tmp;
  999. X    }
  1000. X    lastbuf = t->stptr;
  1001. X    do {
  1002. X        if (re_search(rp, t->stptr, t->stlen, search_start,
  1003. X            t->stlen-search_start, &reregs) == -1
  1004. X            || reregs.start[0] == reregs.end[0])
  1005. X            break;
  1006. X        matches++;
  1007. X
  1008. X        /*
  1009. X         * first, make a pass through the sub. pattern, to calculate
  1010. X         * the length of the string after substitution 
  1011. X         */
  1012. X        match_length = reregs.end[0] - reregs.start[0];
  1013. X        len = t->stlen - match_length;
  1014. X        for (scan = s->stptr; scan < s->stptr + s->stlen; scan++)
  1015. X            if (*scan == '&')
  1016. X                len += match_length;
  1017. X            else if (*scan == '\\' && *(scan+1) == '&') {
  1018. X                scan++;
  1019. X                len++;
  1020. X            } else
  1021. X                len++;
  1022. X        emalloc(buf, char *, len + 1, "do_sub");
  1023. X        bp = buf;
  1024. X
  1025. X        /*
  1026. X         * now, create the result, copying in parts of the original
  1027. X         * string 
  1028. X         */
  1029. X        for (scan = t->stptr; scan < t->stptr + reregs.start[0]; scan++)
  1030. X            *bp++ = *scan;
  1031. X        for (scan = s->stptr; scan < s->stptr + s->stlen; scan++)
  1032. X            if (*scan == '&')
  1033. X                for (cp = t->stptr + reregs.start[0];
  1034. X                     cp < t->stptr + reregs.end[0]; cp++)
  1035. X                    *bp++ = *cp;
  1036. X            else if (*scan == '\\' && *(scan+1) == '&') {
  1037. X                scan++;
  1038. X                *bp++ = *scan;
  1039. X            } else
  1040. X                *bp++ = *scan;
  1041. X        search_start = bp - buf;
  1042. X        for (scan = t->stptr + reregs.end[0];
  1043. X             scan < t->stptr + t->stlen; scan++)
  1044. X            *bp++ = *scan;
  1045. X        *bp = '\0';
  1046. X        free(lastbuf);
  1047. X        t->stptr = buf;
  1048. X        lastbuf = buf;
  1049. X        t->stlen = len;
  1050. X    } while (global && search_start < t->stlen);
  1051. X
  1052. X    free_temp(s);
  1053. X    if (need_to_free) {
  1054. X        free(rp->buffer);
  1055. X        free(rp->fastmap);
  1056. X        free((char *) rp);
  1057. X    }
  1058. X    if (matches > 0) {
  1059. X        if (field_num == 0)
  1060. X            set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
  1061. X        t->flags &= ~(NUM|NUMERIC);
  1062. X    }
  1063. X    field_num = -1;
  1064. X    return tmp_number((AWKNUM) matches);
  1065. X}
  1066. X
  1067. XNODE *
  1068. Xdo_gsub(tree)
  1069. XNODE *tree;
  1070. X{
  1071. X    return sub_common(tree, 1);
  1072. X}
  1073. X
  1074. XNODE *
  1075. Xdo_sub(tree)
  1076. XNODE *tree;
  1077. X{
  1078. X    return sub_common(tree, 0);
  1079. X}
  1080. X
  1081. END_OF_FILE
  1082.   if test 20659 -ne `wc -c <'./builtin.c'`; then
  1083.     echo shar: \"'./builtin.c'\" unpacked with wrong size!
  1084.   fi
  1085.   # end of './builtin.c'
  1086. fi
  1087. if test -f './eval.c' -a "${1}" != "-c" ; then 
  1088.   echo shar: Will not clobber existing file \"'./eval.c'\"
  1089. else
  1090.   echo shar: Extracting \"'./eval.c'\" \(29550 characters\)
  1091.   sed "s/^X//" >'./eval.c' <<'END_OF_FILE'
  1092. X/*
  1093. X * eval.c - gawk parse tree interpreter 
  1094. X */
  1095. X
  1096. X/* 
  1097. X * Copyright (C) 1986, 1988, 1989 the Free Software Foundation, Inc.
  1098. X * 
  1099. X * This file is part of GAWK, the GNU implementation of the
  1100. X * AWK Progamming Language.
  1101. X * 
  1102. X * GAWK is free software; you can redistribute it and/or modify
  1103. X * it under the terms of the GNU General Public License as published by
  1104. X * the Free Software Foundation; either version 1, or (at your option)
  1105. X * any later version.
  1106. X * 
  1107. X * GAWK is distributed in the hope that it will be useful,
  1108. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1109. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1110. X * GNU General Public License for more details.
  1111. X * 
  1112. X * You should have received a copy of the GNU General Public License
  1113. X * along with GAWK; see the file COPYING.  If not, write to
  1114. X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  1115. X */
  1116. X
  1117. X#include "awk.h"
  1118. X
  1119. Xextern void do_print();
  1120. Xextern void do_printf();
  1121. Xextern NODE *do_match();
  1122. Xextern NODE *do_sub();
  1123. Xextern NODE *do_getline();
  1124. Xextern NODE *concat_exp();
  1125. Xextern int in_array();
  1126. Xextern void do_delete();
  1127. Xextern double pow();
  1128. X
  1129. Xstatic int eval_condition();
  1130. Xstatic NODE *op_assign();
  1131. Xstatic NODE *func_call();
  1132. Xstatic NODE *match_op();
  1133. X
  1134. XNODE *_t;        /* used as a temporary in macros */
  1135. X#ifdef MSDOS
  1136. Xdouble _msc51bug;    /* to get around a bug in MSC 5.1 */
  1137. X#endif
  1138. XNODE *ret_node;
  1139. X
  1140. X/* More of that debugging stuff */
  1141. X#ifdef    DEBUG
  1142. X#define DBG_P(X) print_debug X
  1143. X#else
  1144. X#define DBG_P(X)
  1145. X#endif
  1146. X
  1147. X/* Macros and variables to save and restore function and loop bindings */
  1148. X/*
  1149. X * the val variable allows return/continue/break-out-of-context to be
  1150. X * caught and diagnosed
  1151. X */
  1152. X#define PUSH_BINDING(stack, x, val) (memcpy ((char *)(stack), (char *)(x), sizeof (jmp_buf)), val++)
  1153. X#define RESTORE_BINDING(stack, x, val) (memcpy ((char *)(x), (char *)(stack), sizeof (jmp_buf)), val--)
  1154. X
  1155. Xstatic jmp_buf loop_tag;    /* always the current binding */
  1156. Xstatic int loop_tag_valid = 0;    /* nonzero when loop_tag valid */
  1157. Xstatic int func_tag_valid = 0;
  1158. Xstatic jmp_buf func_tag;
  1159. Xextern int exiting, exit_val;
  1160. X
  1161. X/*
  1162. X * This table is used by the regexp routines to do case independant
  1163. X * matching. Basically, every ascii character maps to itself, except
  1164. X * uppercase letters map to lower case ones. This table has 256
  1165. X * entries, which may be overkill. Note also that if the system this
  1166. X * is compiled on doesn't use 7-bit ascii, casetable[] should not be
  1167. X * defined to the linker, so gawk should not load.
  1168. X *
  1169. X * Do NOT make this array static, it is used in several spots, not
  1170. X * just in this file.
  1171. X */
  1172. X#if 'a' == 97    /* it's ascii */
  1173. Xchar casetable[] = {
  1174. X    '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
  1175. X    '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
  1176. X    '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
  1177. X    '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
  1178. X    /* ' '     '!'     '"'     '#'     '$'     '%'     '&'     ''' */
  1179. X    '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
  1180. X    /* '('     ')'     '*'     '+'     ','     '-'     '.'     '/' */
  1181. X    '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
  1182. X    /* '0'     '1'     '2'     '3'     '4'     '5'     '6'     '7' */
  1183. X    '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
  1184. X    /* '8'     '9'     ':'     ';'     '<'     '='     '>'     '?' */
  1185. X    '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
  1186. X    /* '@'     'A'     'B'     'C'     'D'     'E'     'F'     'G' */
  1187. X    '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  1188. X    /* 'H'     'I'     'J'     'K'     'L'     'M'     'N'     'O' */
  1189. X    '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  1190. X    /* 'P'     'Q'     'R'     'S'     'T'     'U'     'V'     'W' */
  1191. X    '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  1192. X    /* 'X'     'Y'     'Z'     '['     '\'     ']'     '^'     '_' */
  1193. X    '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
  1194. X    /* '`'     'a'     'b'     'c'     'd'     'e'     'f'     'g' */
  1195. X    '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  1196. X    /* 'h'     'i'     'j'     'k'     'l'     'm'     'n'     'o' */
  1197. X    '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  1198. X    /* 'p'     'q'     'r'     's'     't'     'u'     'v'     'w' */
  1199. X    '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  1200. X    /* 'x'     'y'     'z'     '{'     '|'     '}'     '~' */
  1201. X    '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
  1202. X    '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
  1203. X    '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
  1204. X    '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
  1205. X    '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
  1206. X    '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
  1207. X    '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
  1208. X    '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
  1209. X    '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
  1210. X    '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
  1211. X    '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
  1212. X    '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
  1213. X    '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
  1214. X    '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  1215. X    '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  1216. X    '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  1217. X    '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
  1218. X};
  1219. X#else
  1220. X#include "You lose. You will need a translation table for your character set."
  1221. X#endif
  1222. X
  1223. X/*
  1224. X * Tree is a bunch of rules to run. Returns zero if it hit an exit()
  1225. X * statement 
  1226. X */
  1227. Xint
  1228. Xinterpret(tree)
  1229. XNODE *tree;
  1230. X{
  1231. X    volatile jmp_buf loop_tag_stack; /* shallow binding stack for loop_tag */
  1232. X    static jmp_buf rule_tag;/* tag the rule currently being run, for NEXT
  1233. X                 * and EXIT statements.  It is static because
  1234. X                 * there are no nested rules */
  1235. X    register NODE *t = NULL;/* temporary */
  1236. X    volatile NODE **lhs;    /* lhs == Left Hand Side for assigns, etc */
  1237. X    volatile struct search *l;    /* For array_for */
  1238. X    volatile NODE *stable_tree;
  1239. X
  1240. X    if (tree == NULL)
  1241. X        return 1;
  1242. X    sourceline = tree->source_line;
  1243. X    source = tree->source_file;
  1244. X    switch (tree->type) {
  1245. X    case Node_rule_list:
  1246. X        for (t = tree; t != NULL; t = t->rnode) {
  1247. X            tree = t->lnode;
  1248. X        /* FALL THROUGH */
  1249. X    case Node_rule_node:
  1250. X            sourceline = tree->source_line;
  1251. X            source = tree->source_file;
  1252. X            switch (setjmp(rule_tag)) {
  1253. X            case 0:    /* normal non-jump */
  1254. X                /* test pattern, if any */
  1255. X                if (tree->lnode == NULL 
  1256. X                    || eval_condition(tree->lnode)) {
  1257. X                    DBG_P(("Found a rule", tree->rnode));
  1258. X                    if (tree->rnode == NULL) {
  1259. X                        /*
  1260. X                         * special case: pattern with
  1261. X                         * no action is equivalent to
  1262. X                         * an action of {print}
  1263. X                         */
  1264. X                        NODE printnode;
  1265. X
  1266. X                        printnode.type = Node_K_print;
  1267. X                        printnode.lnode = NULL;
  1268. X                        printnode.rnode = NULL;
  1269. X                        do_print(&printnode);
  1270. X                    } else if (tree->rnode->type == Node_illegal) {
  1271. X                        /*
  1272. X                         * An empty statement
  1273. X                         * (``{ }'') is different
  1274. X                         * from a missing statement.
  1275. X                         * A missing statement is
  1276. X                         * equal to ``{ print }'' as
  1277. X                         * above, but an empty
  1278. X                         * statement is as in C, do
  1279. X                         * nothing.
  1280. X                         */
  1281. X                    } else
  1282. X                        (void) interpret(tree->rnode);
  1283. X                }
  1284. X                break;
  1285. X            case TAG_CONTINUE:    /* NEXT statement */
  1286. X                return 1;
  1287. X            case TAG_BREAK:
  1288. X                return 0;
  1289. X            default:
  1290. X                cant_happen();
  1291. X            }
  1292. X            if (t == NULL)
  1293. X                break;
  1294. X        }
  1295. X        break;
  1296. X
  1297. X    case Node_statement_list:
  1298. X        for (t = tree; t != NULL; t = t->rnode) {
  1299. X            DBG_P(("Statements", t->lnode));
  1300. X            (void) interpret(t->lnode);
  1301. X        }
  1302. X        break;
  1303. X
  1304. X    case Node_K_if:
  1305. X        DBG_P(("IF", tree->lnode));
  1306. X        if (eval_condition(tree->lnode)) {
  1307. X            DBG_P(("True", tree->rnode->lnode));
  1308. X            (void) interpret(tree->rnode->lnode);
  1309. X        } else {
  1310. X            DBG_P(("False", tree->rnode->rnode));
  1311. X            (void) interpret(tree->rnode->rnode);
  1312. X        }
  1313. X        break;
  1314. X
  1315. X    case Node_K_while:
  1316. X        PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  1317. X
  1318. X        DBG_P(("WHILE", tree->lnode));
  1319. X        stable_tree = tree;
  1320. X        while (eval_condition(stable_tree->lnode)) {
  1321. X            switch (setjmp(loop_tag)) {
  1322. X            case 0:    /* normal non-jump */
  1323. X                DBG_P(("DO", stable_tree->rnode));
  1324. X                (void) interpret(stable_tree->rnode);
  1325. X                break;
  1326. X            case TAG_CONTINUE:    /* continue statement */
  1327. X                break;
  1328. X            case TAG_BREAK:    /* break statement */
  1329. X                RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  1330. X                return 1;
  1331. X            default:
  1332. X                cant_happen();
  1333. X            }
  1334. X        }
  1335. X        RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  1336. X        break;
  1337. X
  1338. X    case Node_K_do:
  1339. X        PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  1340. X        stable_tree = tree;
  1341. X        do {
  1342. X            switch (setjmp(loop_tag)) {
  1343. X            case 0:    /* normal non-jump */
  1344. X                DBG_P(("DO", stable_tree->rnode));
  1345. X                (void) interpret(stable_tree->rnode);
  1346. X                break;
  1347. X            case TAG_CONTINUE:    /* continue statement */
  1348. X                break;
  1349. X            case TAG_BREAK:    /* break statement */
  1350. X                RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  1351. X                return 1;
  1352. X            default:
  1353. X                cant_happen();
  1354. X            }
  1355. X            DBG_P(("WHILE", stable_tree->lnode));
  1356. X        } while (eval_condition(stable_tree->lnode));
  1357. X        RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  1358. X        break;
  1359. X
  1360. X    case Node_K_for:
  1361. X        PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  1362. X        DBG_P(("FOR", tree->forloop->init));
  1363. X        (void) interpret(tree->forloop->init);
  1364. X        DBG_P(("FOR.WHILE", tree->forloop->cond));
  1365. X        stable_tree = tree;
  1366. X        while (eval_condition(stable_tree->forloop->cond)) {
  1367. X            switch (setjmp(loop_tag)) {
  1368. X            case 0:    /* normal non-jump */
  1369. X                DBG_P(("FOR.DO", stable_tree->lnode));
  1370. X                (void) interpret(stable_tree->lnode);
  1371. X                /* fall through */
  1372. X            case TAG_CONTINUE:    /* continue statement */
  1373. X                DBG_P(("FOR.INCR", stable_tree->forloop->incr));
  1374. X                (void) interpret(stable_tree->forloop->incr);
  1375. X                break;
  1376. X            case TAG_BREAK:    /* break statement */
  1377. X                RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  1378. X                return 1;
  1379. X            default:
  1380. X                cant_happen();
  1381. X            }
  1382. X        }
  1383. X        RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  1384. X        break;
  1385. X
  1386. X    case Node_K_arrayfor:
  1387. X#define hakvar forloop->init
  1388. X#define arrvar forloop->incr
  1389. X        PUSH_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  1390. X        DBG_P(("AFOR.VAR", tree->hakvar));
  1391. X        lhs = (volatile NODE **) get_lhs(tree->hakvar, 1);
  1392. X        t = tree->arrvar;
  1393. X        if (t->type == Node_param_list)
  1394. X            t = stack_ptr[t->param_cnt];
  1395. X        stable_tree = tree;
  1396. X        for (l = assoc_scan(t); l; l = assoc_next((struct search *)l)) {
  1397. X            deref = *((NODE **) lhs);
  1398. X            do_deref();
  1399. X            *lhs = dupnode(l->retval);
  1400. X            if (field_num == 0)
  1401. X                set_record(fields_arr[0]->stptr,
  1402. X                    fields_arr[0]->stlen);
  1403. X            DBG_P(("AFOR.NEXTIS", *lhs));
  1404. X            switch (setjmp(loop_tag)) {
  1405. X            case 0:
  1406. X                DBG_P(("AFOR.DO", stable_tree->lnode));
  1407. X                (void) interpret(stable_tree->lnode);
  1408. X            case TAG_CONTINUE:
  1409. X                break;
  1410. X
  1411. X            case TAG_BREAK:
  1412. X                RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  1413. X                field_num = -1;
  1414. X                return 1;
  1415. X            default:
  1416. X                cant_happen();
  1417. X            }
  1418. X        }
  1419. X        field_num = -1;
  1420. X        RESTORE_BINDING(loop_tag_stack, loop_tag, loop_tag_valid);
  1421. X        break;
  1422. X
  1423. X    case Node_K_break:
  1424. X        DBG_P(("BREAK", NULL));
  1425. X        if (loop_tag_valid == 0)
  1426. X            fatal("unexpected break");
  1427. X        longjmp(loop_tag, TAG_BREAK);
  1428. X        break;
  1429. X
  1430. X    case Node_K_continue:
  1431. X        DBG_P(("CONTINUE", NULL));
  1432. X        if (loop_tag_valid == 0)
  1433. X            fatal("unexpected continue");
  1434. X        longjmp(loop_tag, TAG_CONTINUE);
  1435. X        break;
  1436. X
  1437. X    case Node_K_print:
  1438. X        DBG_P(("PRINT", tree));
  1439. X        do_print(tree);
  1440. X        break;
  1441. X
  1442. X    case Node_K_printf:
  1443. X        DBG_P(("PRINTF", tree));
  1444. X        do_printf(tree);
  1445. X        break;
  1446. X
  1447. X    case Node_K_next:
  1448. X        DBG_P(("NEXT", NULL));
  1449. X        longjmp(rule_tag, TAG_CONTINUE);
  1450. X        break;
  1451. X
  1452. X    case Node_K_exit:
  1453. X        /*
  1454. X         * In A,K,&W, p. 49, it says that an exit statement "...
  1455. X         * causes the program to behave as if the end of input had
  1456. X         * occurred; no more input is read, and the END actions, if
  1457. X         * any are executed." This implies that the rest of the rules
  1458. X         * are not done. So we immediately break out of the main loop.
  1459. X         */
  1460. X        DBG_P(("EXIT", NULL));
  1461. X        exiting = 1;
  1462. X        if (tree) {
  1463. X            t = tree_eval(tree->lnode);
  1464. X            exit_val = (int) force_number(t);
  1465. X        }
  1466. X        free_temp(t);
  1467. X        longjmp(rule_tag, TAG_BREAK);
  1468. X        break;
  1469. X
  1470. X    case Node_K_return:
  1471. X        DBG_P(("RETURN", NULL));
  1472. X        t = tree_eval(tree->lnode);
  1473. X        ret_node = dupnode(t);
  1474. X        free_temp(t);
  1475. X        longjmp(func_tag, TAG_RETURN);
  1476. X        break;
  1477. X
  1478. X    default:
  1479. X        /*
  1480. X         * Appears to be an expression statement.  Throw away the
  1481. X         * value. 
  1482. X         */
  1483. X        DBG_P(("E", NULL));
  1484. X        t = tree_eval(tree);
  1485. X        free_temp(t);
  1486. X        break;
  1487. X    }
  1488. X    return 1;
  1489. X}
  1490. X
  1491. X/* evaluate a subtree, allocating strings on a temporary stack. */
  1492. X
  1493. XNODE *
  1494. Xr_tree_eval(tree)
  1495. XNODE *tree;
  1496. X{
  1497. X    register NODE *r, *t1, *t2;    /* return value & temporary subtrees */
  1498. X    int i;
  1499. X    register NODE **lhs;
  1500. X    int di;
  1501. X    AWKNUM x, x2;
  1502. X    long lx;
  1503. X    extern NODE **fields_arr;
  1504. X
  1505. X    source = tree->source_file;
  1506. X    sourceline = tree->source_line;
  1507. X    switch (tree->type) {
  1508. X    case Node_and:
  1509. X        DBG_P(("AND", tree));
  1510. X        return tmp_number((AWKNUM) (eval_condition(tree->lnode)
  1511. X                        && eval_condition(tree->rnode)));
  1512. X
  1513. X    case Node_or:
  1514. X        DBG_P(("OR", tree));
  1515. X        return tmp_number((AWKNUM) (eval_condition(tree->lnode)
  1516. X                        || eval_condition(tree->rnode)));
  1517. X
  1518. X    case Node_not:
  1519. X        DBG_P(("NOT", tree));
  1520. X        return tmp_number((AWKNUM) ! eval_condition(tree->lnode));
  1521. X
  1522. X        /* Builtins */
  1523. X    case Node_builtin:
  1524. X        DBG_P(("builtin", tree));
  1525. X        return ((*tree->proc) (tree->subnode));
  1526. X
  1527. X    case Node_K_getline:
  1528. X        DBG_P(("GETLINE", tree));
  1529. X        return (do_getline(tree));
  1530. X
  1531. X    case Node_in_array:
  1532. X        DBG_P(("IN_ARRAY", tree));
  1533. X        return tmp_number((AWKNUM) in_array(tree->lnode, tree->rnode));
  1534. X
  1535. X    case Node_func_call:
  1536. X        DBG_P(("func_call", tree));
  1537. X        return func_call(tree->rnode, tree->lnode);
  1538. X
  1539. X    case Node_K_delete:
  1540. X        DBG_P(("DELETE", tree));
  1541. X        do_delete(tree->lnode, tree->rnode);
  1542. X        return Nnull_string;
  1543. X
  1544. X        /* unary operations */
  1545. X
  1546. X    case Node_var:
  1547. X    case Node_var_array:
  1548. X    case Node_param_list:
  1549. X    case Node_subscript:
  1550. X    case Node_field_spec:
  1551. X        DBG_P(("var_type ref", tree));
  1552. X        lhs = get_lhs(tree, 0);
  1553. X        field_num = -1;
  1554. X        deref = 0;
  1555. X        return *lhs;
  1556. X
  1557. X    case Node_unary_minus:
  1558. X        DBG_P(("UMINUS", tree));
  1559. X        t1 = tree_eval(tree->subnode);
  1560. X        x = -force_number(t1);
  1561. X        free_temp(t1);
  1562. X        return tmp_number(x);
  1563. X
  1564. X    case Node_cond_exp:
  1565. X        DBG_P(("?:", tree));
  1566. X        if (eval_condition(tree->lnode)) {
  1567. X            DBG_P(("True", tree->rnode->lnode));
  1568. X            return tree_eval(tree->rnode->lnode);
  1569. X        }
  1570. X        DBG_P(("False", tree->rnode->rnode));
  1571. X        return tree_eval(tree->rnode->rnode);
  1572. X
  1573. X    case Node_match:
  1574. X    case Node_nomatch:
  1575. X    case Node_regex:
  1576. X        DBG_P(("[no]match_op", tree));
  1577. X        return match_op(tree);
  1578. X
  1579. X    case Node_func:
  1580. X        fatal("function `%s' called with space between name and (,\n%s",
  1581. X            tree->lnode->param,
  1582. X            "or used in other expression context");
  1583. X
  1584. X    /* assignments */
  1585. X    case Node_assign:
  1586. X        DBG_P(("ASSIGN", tree));
  1587. X        r = tree_eval(tree->rnode);
  1588. X        lhs = get_lhs(tree->lnode, 1);
  1589. X        *lhs = dupnode(r);
  1590. X        free_temp(r);
  1591. X        do_deref();
  1592. X        if (field_num == 0)
  1593. X            set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
  1594. X        field_num = -1;
  1595. X        return *lhs;
  1596. X
  1597. X    /* other assignment types are easier because they are numeric */
  1598. X    case Node_preincrement:
  1599. X    case Node_predecrement:
  1600. X    case Node_postincrement:
  1601. X    case Node_postdecrement:
  1602. X    case Node_assign_exp:
  1603. X    case Node_assign_times:
  1604. X    case Node_assign_quotient:
  1605. X    case Node_assign_mod:
  1606. X    case Node_assign_plus:
  1607. X    case Node_assign_minus:
  1608. X        return op_assign(tree);
  1609. X    default:
  1610. X        break;    /* handled below */
  1611. X    }
  1612. X
  1613. X    /* evaluate subtrees in order to do binary operation, then keep going */
  1614. X    t1 = tree_eval(tree->lnode);
  1615. X    t2 = tree_eval(tree->rnode);
  1616. X
  1617. X    switch (tree->type) {
  1618. X    case Node_concat:
  1619. X        DBG_P(("CONCAT", tree));
  1620. X        t1 = force_string(t1);
  1621. X        t2 = force_string(t2);
  1622. X
  1623. X        r = newnode(Node_val);
  1624. X        r->flags |= (STR|TEMP);
  1625. X        r->stlen = t1->stlen + t2->stlen;
  1626. X        r->stref = 1;
  1627. X        emalloc(r->stptr, char *, r->stlen + 1, "tree_eval");
  1628. X        memcpy(r->stptr, t1->stptr, t1->stlen);
  1629. X        memcpy(r->stptr + t1->stlen, t2->stptr, t2->stlen + 1);
  1630. X        free_temp(t1);
  1631. X        free_temp(t2);
  1632. X        return r;
  1633. X
  1634. X    case Node_geq:
  1635. X    case Node_leq:
  1636. X    case Node_greater:
  1637. X    case Node_less:
  1638. X    case Node_notequal:
  1639. X    case Node_equal:
  1640. X        di = cmp_nodes(t1, t2);
  1641. X        free_temp(t1);
  1642. X        free_temp(t2);
  1643. X        switch (tree->type) {
  1644. X        case Node_equal:
  1645. X            DBG_P(("EQUAL", tree));
  1646. X            return tmp_number((AWKNUM) (di == 0));
  1647. X        case Node_notequal:
  1648. X            DBG_P(("NOT_EQUAL", tree));
  1649. X            return tmp_number((AWKNUM) (di != 0));
  1650. X        case Node_less:
  1651. X            DBG_P(("LESS_THAN", tree));
  1652. X            return tmp_number((AWKNUM) (di < 0));
  1653. X        case Node_greater:
  1654. X            DBG_P(("GREATER_THAN", tree));
  1655. X            return tmp_number((AWKNUM) (di > 0));
  1656. X        case Node_leq:
  1657. X            DBG_P(("LESS_THAN_EQUAL", tree));
  1658. X            return tmp_number((AWKNUM) (di <= 0));
  1659. X        case Node_geq:
  1660. X            DBG_P(("GREATER_THAN_EQUAL", tree));
  1661. X            return tmp_number((AWKNUM) (di >= 0));
  1662. X        default:
  1663. X            cant_happen();
  1664. X        }
  1665. X        break;
  1666. X    default:
  1667. X        break;    /* handled below */
  1668. X    }
  1669. X
  1670. X    (void) force_number(t1);
  1671. X    (void) force_number(t2);
  1672. X
  1673. X    switch (tree->type) {
  1674. X    case Node_exp:
  1675. X        DBG_P(("EXPONENT", tree));
  1676. X        if ((lx = t2->numbr) == t2->numbr) {    /* integer exponent */
  1677. X            if (lx == 0)
  1678. X                x = 1;
  1679. X            else if (lx == 1)
  1680. X                x = t1->numbr;
  1681. X            else {
  1682. X                /* doing it this way should be more precise */
  1683. X                for (x = x2 = t1->numbr; --lx; )
  1684. X                    x *= x2;
  1685. X            }
  1686. X        } else
  1687. X            x = pow((double) t1->numbr, (double) t2->numbr);
  1688. X        free_temp(t1);
  1689. X        free_temp(t2);
  1690. X        return tmp_number(x);
  1691. X
  1692. X    case Node_times:
  1693. X        DBG_P(("MULT", tree));
  1694. X        x = t1->numbr * t2->numbr;
  1695. X        free_temp(t1);
  1696. X        free_temp(t2);
  1697. X        return tmp_number(x);
  1698. X
  1699. X    case Node_quotient:
  1700. X        DBG_P(("DIVIDE", tree));
  1701. X        x = t2->numbr;
  1702. X        free_temp(t2);
  1703. X        if (x == (AWKNUM) 0)
  1704. X            fatal("division by zero attempted");
  1705. X            /* NOTREACHED */
  1706. X        else {
  1707. X            x = t1->numbr / x;
  1708. X            free_temp(t1);
  1709. X            return tmp_number(x);
  1710. X        }
  1711. X
  1712. X    case Node_mod:
  1713. X        DBG_P(("MODULUS", tree));
  1714. X        x = t2->numbr;
  1715. X        free_temp(t2);
  1716. X        if (x == (AWKNUM) 0)
  1717. X            fatal("division by zero attempted in mod");
  1718. X            /* NOTREACHED */
  1719. X        lx = t1->numbr / x;    /* assignment to long truncates */
  1720. X        x2 = lx * x;
  1721. X        x = t1->numbr - x2;
  1722. X        free_temp(t1);
  1723. X        return tmp_number(x);
  1724. X
  1725. X    case Node_plus:
  1726. X        DBG_P(("PLUS", tree));
  1727. X        x = t1->numbr + t2->numbr;
  1728. X        free_temp(t1);
  1729. X        free_temp(t2);
  1730. X        return tmp_number(x);
  1731. X
  1732. X    case Node_minus:
  1733. X        DBG_P(("MINUS", tree));
  1734. X        x = t1->numbr - t2->numbr;
  1735. X        free_temp(t1);
  1736. X        free_temp(t2);
  1737. X        return tmp_number(x);
  1738. X
  1739. X    default:
  1740. X        fatal("illegal type (%d) in tree_eval", tree->type);
  1741. X    }
  1742. X    return 0;
  1743. X}
  1744. X
  1745. X/*
  1746. X * This makes numeric operations slightly more efficient. Just change the
  1747. X * value of a numeric node, if possible 
  1748. X */
  1749. Xvoid
  1750. Xassign_number(ptr, value)
  1751. XNODE **ptr;
  1752. XAWKNUM value;
  1753. X{
  1754. X    extern NODE *deref;
  1755. X    register NODE *n = *ptr;
  1756. X
  1757. X#ifdef DEBUG
  1758. X    if (n->type != Node_val)
  1759. X        cant_happen();
  1760. X#endif
  1761. X    if (n == Nnull_string) {
  1762. X        *ptr = make_number(value);
  1763. X        deref = 0;
  1764. X        return;
  1765. X    }
  1766. X    if (n->stref > 1) {
  1767. X        *ptr = make_number(value);
  1768. X        return;
  1769. X    }
  1770. X    if ((n->flags & STR) && (n->flags & (MALLOC|TEMP)))
  1771. X        free(n->stptr);
  1772. X    n->numbr = value;
  1773. X    n->flags |= (NUM|NUMERIC);
  1774. X    n->flags &= ~STR;
  1775. X    n->stref = 0;
  1776. X    deref = 0;
  1777. X}
  1778. X
  1779. X
  1780. X/* Is TREE true or false?  Returns 0==false, non-zero==true */
  1781. Xstatic int
  1782. Xeval_condition(tree)
  1783. XNODE *tree;
  1784. X{
  1785. X    register NODE *t1;
  1786. X    int ret;
  1787. X
  1788. X    if (tree == NULL)    /* Null trees are the easiest kinds */
  1789. X        return 1;
  1790. X    if (tree->type == Node_line_range) {
  1791. X        /*
  1792. X         * Node_line_range is kind of like Node_match, EXCEPT: the
  1793. X         * lnode field (more properly, the condpair field) is a node
  1794. X         * of a Node_cond_pair; whether we evaluate the lnode of that
  1795. X         * node or the rnode depends on the triggered word.  More
  1796. X         * precisely:  if we are not yet triggered, we tree_eval the
  1797. X         * lnode; if that returns true, we set the triggered word. 
  1798. X         * If we are triggered (not ELSE IF, note), we tree_eval the
  1799. X         * rnode, clear triggered if it succeeds, and perform our
  1800. X         * action (regardless of success or failure).  We want to be
  1801. X         * able to begin and end on a single input record, so this
  1802. X         * isn't an ELSE IF, as noted above.
  1803. X         */
  1804. X        if (!tree->triggered)
  1805. X            if (!eval_condition(tree->condpair->lnode))
  1806. X                return 0;
  1807. X            else
  1808. X                tree->triggered = 1;
  1809. X        /* Else we are triggered */
  1810. X        if (eval_condition(tree->condpair->rnode))
  1811. X            tree->triggered = 0;
  1812. X        return 1;
  1813. X    }
  1814. X
  1815. X    /*
  1816. X     * Could just be J.random expression. in which case, null and 0 are
  1817. X     * false, anything else is true 
  1818. X     */
  1819. X
  1820. X    t1 = tree_eval(tree);
  1821. X    if (t1->flags & NUMERIC)
  1822. X        ret = t1->numbr != 0.0;
  1823. X    else
  1824. X        ret = t1->stlen != 0;
  1825. X    free_temp(t1);
  1826. X    return ret;
  1827. X}
  1828. X
  1829. Xint
  1830. Xcmp_nodes(t1, t2)
  1831. XNODE *t1, *t2;
  1832. X{
  1833. X    AWKNUM d;
  1834. X    AWKNUM d1;
  1835. X    AWKNUM d2;
  1836. X    int ret;
  1837. X    int len1, len2;
  1838. X
  1839. X    if (t1 == t2)
  1840. X        return 0;
  1841. X    d1 = force_number(t1);
  1842. X    d2 = force_number(t2);
  1843. X    if ((t1->flags & NUMERIC) && (t2->flags & NUMERIC)) {
  1844. X        d = d1 - d2;
  1845. X        if (d == 0.0)    /* from profiling, this is most common */
  1846. X            return 0;
  1847. X        if (d > 0.0)
  1848. X            return 1;
  1849. X        return -1;
  1850. X    }
  1851. X    t1 = force_string(t1);
  1852. X    t2 = force_string(t2);
  1853. X    len1 = t1->stlen;
  1854. X    len2 = t2->stlen;
  1855. X    if (len1 == 0) {
  1856. X        if (len2 == 0)
  1857. X            return 0;
  1858. X        else
  1859. X            return -1;
  1860. X    } else if (len2 == 0)
  1861. X        return 1;
  1862. X    ret = memcmp(t1->stptr, t2->stptr, len1 <= len2 ? len1 : len2);
  1863. X    if (ret == 0 && len1 != len2)
  1864. X        return len1 < len2 ? -1: 1;
  1865. X    return ret;
  1866. X}
  1867. X
  1868. Xstatic NODE *
  1869. Xop_assign(tree)
  1870. XNODE *tree;
  1871. X{
  1872. X    AWKNUM rval, lval;
  1873. X    NODE **lhs;
  1874. X    AWKNUM t1, t2;
  1875. X    long ltemp;
  1876. X    NODE *tmp;
  1877. X
  1878. X    lhs = get_lhs(tree->lnode, 1);
  1879. X    lval = force_number(*lhs);
  1880. X
  1881. X    switch(tree->type) {
  1882. X    case Node_preincrement:
  1883. X    case Node_predecrement:
  1884. X        DBG_P(("+-X", tree));
  1885. X        assign_number(lhs,
  1886. X            lval + (tree->type == Node_preincrement ? 1.0 : -1.0));
  1887. X        do_deref();
  1888. X        if (field_num == 0)
  1889. X            set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
  1890. X        field_num = -1;
  1891. X        return *lhs;
  1892. X
  1893. X    case Node_postincrement:
  1894. X    case Node_postdecrement:
  1895. X        DBG_P(("X+-", tree));
  1896. X        assign_number(lhs,
  1897. X            lval + (tree->type == Node_postincrement ? 1.0 : -1.0));
  1898. X        do_deref();
  1899. X        if (field_num == 0)
  1900. X            set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
  1901. X        field_num = -1;
  1902. X        return tmp_number(lval);
  1903. X    default:
  1904. X        break;    /* handled below */
  1905. X    }
  1906. X
  1907. X    tmp = tree_eval(tree->rnode);
  1908. X    rval = force_number(tmp);
  1909. X    free_temp(tmp);
  1910. X    switch(tree->type) {
  1911. X    case Node_assign_exp:
  1912. X        DBG_P(("ASSIGN_exp", tree));
  1913. X        if ((ltemp = rval) == rval) {    /* integer exponent */
  1914. X            if (ltemp == 0)
  1915. X                assign_number(lhs, (AWKNUM) 1);
  1916. X            else if (ltemp == 1)
  1917. X                assign_number(lhs, lval);
  1918. X            else {
  1919. X                /* doing it this way should be more precise */
  1920. X                for (t1 = t2 = lval; --ltemp; )
  1921. X                    t1 *= t2;
  1922. X                assign_number(lhs, t1);
  1923. X            }
  1924. X        } else
  1925. X            assign_number(lhs, (AWKNUM) pow((double) lval, (double) rval));
  1926. X        break;
  1927. X
  1928. X    case Node_assign_times:
  1929. X        DBG_P(("ASSIGN_times", tree));
  1930. X        assign_number(lhs, lval * rval);
  1931. X        break;
  1932. X
  1933. X    case Node_assign_quotient:
  1934. X        DBG_P(("ASSIGN_quotient", tree));
  1935. X        if (rval == (AWKNUM) 0)
  1936. X            fatal("division by zero attempted in /=");
  1937. X        assign_number(lhs, lval / rval);
  1938. X        break;
  1939. X
  1940. X    case Node_assign_mod:
  1941. X        DBG_P(("ASSIGN_mod", tree));
  1942. X        if (rval == (AWKNUM) 0)
  1943. X            fatal("division by zero attempted in %=");
  1944. X        ltemp = lval / rval;    /* assignment to long truncates */
  1945. X        t1 = ltemp * rval;
  1946. X        t2 = lval - t1;
  1947. X        assign_number(lhs, t2);
  1948. X        break;
  1949. X
  1950. X    case Node_assign_plus:
  1951. X        DBG_P(("ASSIGN_plus", tree));
  1952. X        assign_number(lhs, lval + rval);
  1953. X        break;
  1954. X
  1955. X    case Node_assign_minus:
  1956. X        DBG_P(("ASSIGN_minus", tree));
  1957. X        assign_number(lhs, lval - rval);
  1958. X        break;
  1959. X    default:
  1960. X        cant_happen();
  1961. X    }
  1962. X    do_deref();
  1963. X    if (field_num == 0)
  1964. X        set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
  1965. X    field_num = -1;
  1966. X    return *lhs;
  1967. X}
  1968. X
  1969. XNODE **stack_ptr;
  1970. X
  1971. Xstatic NODE *
  1972. Xfunc_call(name, arg_list)
  1973. XNODE *name;        /* name is a Node_val giving function name */
  1974. XNODE *arg_list;        /* Node_expression_list of calling args. */
  1975. X{
  1976. X    register NODE *arg, *argp, *r;
  1977. X    NODE *n, *f;
  1978. X    volatile jmp_buf func_tag_stack;
  1979. X    volatile jmp_buf loop_tag_stack;
  1980. X    volatile int save_loop_tag_valid = 0;
  1981. X    volatile NODE **save_stack, *save_ret_node;
  1982. X    NODE **local_stack, **sp;
  1983. X    int count;
  1984. X    extern NODE *ret_node;
  1985. X
  1986. X    /*
  1987. X     * retrieve function definition node
  1988. X     */
  1989. X    f = lookup(variables, name->stptr);
  1990. X    if (!f || f->type != Node_func)
  1991. X        fatal("function `%s' not defined", name->stptr);
  1992. X#ifdef FUNC_TRACE
  1993. X    fprintf(stderr, "function %s called\n", name->stptr);
  1994. X#endif
  1995. X    count = f->lnode->param_cnt;
  1996. X    emalloc(local_stack, NODE **, count * sizeof(NODE *), "func_call");
  1997. X    sp = local_stack;
  1998. X
  1999. X    /*
  2000. X     * for each calling arg. add NODE * on stack
  2001. X     */
  2002. X    for (argp = arg_list; count && argp != NULL; argp = argp->rnode) {
  2003. X        arg = argp->lnode;
  2004. X        r = newnode(Node_var);
  2005. X        /*
  2006. X         * call by reference for arrays; see below also
  2007. X         */
  2008. X        if (arg->type == Node_param_list)
  2009. X            arg = stack_ptr[arg->param_cnt];
  2010. X        if (arg->type == Node_var_array)
  2011. X            *r = *arg;
  2012. X        else {
  2013. X            n = tree_eval(arg);
  2014. X            r->lnode = dupnode(n);
  2015. X            r->rnode = (NODE *) NULL;
  2016. X            free_temp(n);
  2017. X          }
  2018. X        *sp++ = r;
  2019. X        count--;
  2020. X    }
  2021. X    if (argp != NULL)    /* left over calling args. */
  2022. X        warning(
  2023. X            "function `%s' called with more arguments than declared",
  2024. X            name->stptr);
  2025. X    /*
  2026. X     * add remaining params. on stack with null value
  2027. X     */
  2028. X    while (count-- > 0) {
  2029. X        r = newnode(Node_var);
  2030. X        r->lnode = Nnull_string;
  2031. X        r->rnode = (NODE *) NULL;
  2032. X        *sp++ = r;
  2033. X    }
  2034. X
  2035. X    /*
  2036. X     * Execute function body, saving context, as a return statement
  2037. X     * will longjmp back here.
  2038. X     *
  2039. X     * Have to save and restore the loop_tag stuff so that a return
  2040. X     * inside a loop in a function body doesn't scrog any loops going
  2041. X     * on in the main program.  We save the necessary info in variables
  2042. X     * local to this function so that function nesting works OK.
  2043. X     * We also only bother to save the loop stuff if we're in a loop
  2044. X     * when the function is called.
  2045. X     */
  2046. X    if (loop_tag_valid) {
  2047. X        int junk = 0;
  2048. X
  2049. X        save_loop_tag_valid = (volatile int) loop_tag_valid;
  2050. X        PUSH_BINDING(loop_tag_stack, loop_tag, junk);
  2051. X        loop_tag_valid = 0;
  2052. X    }
  2053. X    save_stack = (volatile NODE **) stack_ptr;
  2054. X    stack_ptr = local_stack;
  2055. X    PUSH_BINDING(func_tag_stack, func_tag, func_tag_valid);
  2056. X    save_ret_node = (volatile NODE *) ret_node;
  2057. X    ret_node = Nnull_string;    /* default return value */
  2058. X    if (setjmp(func_tag) == 0)
  2059. X        (void) interpret(f->rnode);
  2060. X
  2061. X    r = ret_node;
  2062. X    ret_node = (NODE *) save_ret_node;
  2063. X    RESTORE_BINDING(func_tag_stack, func_tag, func_tag_valid);
  2064. X    stack_ptr = (NODE **) save_stack;
  2065. X
  2066. X    /*
  2067. X     * here, we pop each parameter and check whether
  2068. X     * it was an array.  If so, and if the arg. passed in was
  2069. X     * a simple variable, then the value should be copied back.
  2070. X     * This achieves "call-by-reference" for arrays.
  2071. X     */
  2072. X    sp = local_stack;
  2073. X    count = f->lnode->param_cnt;
  2074. X    for (argp = arg_list; count > 0 && argp != NULL; argp = argp->rnode) {
  2075. X        arg = argp->lnode;
  2076. X        n = *sp++;
  2077. X        if (arg->type == Node_var && n->type == Node_var_array) {
  2078. X            arg->var_array = n->var_array;
  2079. X            arg->type = Node_var_array;
  2080. X        }
  2081. X        deref = n->lnode;
  2082. X        do_deref();
  2083. X        freenode(n);
  2084. X        count--;
  2085. X    }
  2086. X    while (count-- > 0) {
  2087. X        n = *sp++;
  2088. X        deref = n->lnode;
  2089. X        do_deref();
  2090. X        freenode(n);
  2091. X    }
  2092. X    free((char *) local_stack);
  2093. X
  2094. X    /* Restore the loop_tag stuff if necessary. */
  2095. X    if (save_loop_tag_valid) {
  2096. X        int junk = 0;
  2097. X
  2098. X        loop_tag_valid = (int) save_loop_tag_valid;
  2099. X        RESTORE_BINDING(loop_tag_stack, loop_tag, junk);
  2100. X    }
  2101. X
  2102. X    if (!(r->flags & PERM))
  2103. X        r->flags |= TEMP;
  2104. X    return r;
  2105. X}
  2106. X
  2107. X/*
  2108. X * This returns a POINTER to a node pointer. get_lhs(ptr) is the current
  2109. X * value of the var, or where to store the var's new value 
  2110. X */
  2111. X
  2112. XNODE **
  2113. Xget_lhs(ptr, assign)
  2114. XNODE *ptr;
  2115. Xint assign;        /* this is being called for the LHS of an assign. */
  2116. X{
  2117. X    register NODE **aptr;
  2118. X    NODE *n;
  2119. X
  2120. X#ifdef DEBUG
  2121. X    if (ptr == NULL)
  2122. X        cant_happen();
  2123. X#endif
  2124. X    deref = NULL;
  2125. X    field_num = -1;
  2126. X    switch (ptr->type) {
  2127. X    case Node_var:
  2128. X    case Node_var_array:
  2129. X        if (ptr == NF_node && (int) NF_node->var_value->numbr == -1)
  2130. X            (void) get_field(HUGE-1, assign); /* parse record */
  2131. X        deref = ptr->var_value;
  2132. X#ifdef DEBUG
  2133. X        if (deref->type != Node_val)
  2134. X            cant_happen();
  2135. X        if (deref->flags == 0)
  2136. X            cant_happen();
  2137. X#endif
  2138. X        return &(ptr->var_value);
  2139. X
  2140. X    case Node_param_list:
  2141. X        n = stack_ptr[ptr->param_cnt];
  2142. X        deref = n->var_value;
  2143. X#ifdef DEBUG
  2144. X        if (deref->type != Node_val)
  2145. X            cant_happen();
  2146. X        if (deref->flags == 0)
  2147. X            cant_happen();
  2148. X#endif
  2149. X        return &(n->var_value);
  2150. X
  2151. X    case Node_field_spec:
  2152. X        n = tree_eval(ptr->lnode);
  2153. X        field_num = (int) force_number(n);
  2154. X        free_temp(n);
  2155. X        if (field_num < 0)
  2156. X            fatal("attempt to access field %d", field_num);
  2157. X        aptr = get_field(field_num, assign);
  2158. X        deref = *aptr;
  2159. X        return aptr;
  2160. X
  2161. X    case Node_subscript:
  2162. X        n = ptr->lnode;
  2163. X        if (n->type == Node_param_list)
  2164. X            n = stack_ptr[n->param_cnt];
  2165. X        aptr = assoc_lookup(n, concat_exp(ptr->rnode));
  2166. X        deref = *aptr;
  2167. X#ifdef DEBUG
  2168. X        if (deref->type != Node_val)
  2169. X            cant_happen();
  2170. X        if (deref->flags == 0)
  2171. X            cant_happen();
  2172. X#endif
  2173. X        return aptr;
  2174. X    case Node_func:
  2175. X        fatal ("`%s' is a function, assignment is not allowed",
  2176. X            ptr->lnode->param);
  2177. X    default:
  2178. X        cant_happen();
  2179. X    }
  2180. X    return 0;
  2181. X}
  2182. X
  2183. Xstatic NODE *
  2184. Xmatch_op(tree)
  2185. XNODE *tree;
  2186. X{
  2187. X    NODE *t1;
  2188. X    struct re_pattern_buffer *rp;
  2189. X    int i;
  2190. X    int match = 1;
  2191. X
  2192. X    if (tree->type == Node_nomatch)
  2193. X        match = 0;
  2194. X    if (tree->type == Node_regex)
  2195. X        t1 = WHOLELINE;
  2196. X    else {
  2197. X        if (tree->lnode)
  2198. X            t1 = force_string(tree_eval(tree->lnode));
  2199. X        else
  2200. X            t1 = WHOLELINE;
  2201. X        tree = tree->rnode;
  2202. X    }
  2203. X    if (tree->type == Node_regex) {
  2204. X        rp = tree->rereg;
  2205. X        if (!strict && ((IGNORECASE_node->var_value->numbr != 0)
  2206. X            ^ (tree->re_case != 0))) {
  2207. X            /* recompile since case sensitivity differs */
  2208. X            rp = tree->rereg =
  2209. X                mk_re_parse(tree->re_text,
  2210. X                (IGNORECASE_node->var_value->numbr != 0));
  2211. X            tree->re_case =
  2212. X                (IGNORECASE_node->var_value->numbr != 0);
  2213. X        }
  2214. X    } else {
  2215. X        rp = make_regexp(force_string(tree_eval(tree)),
  2216. X            (IGNORECASE_node->var_value->numbr != 0));
  2217. X        if (rp == NULL)
  2218. X            cant_happen();
  2219. X    }
  2220. X    i = re_search(rp, t1->stptr, t1->stlen, 0, t1->stlen,
  2221. X        (struct re_registers *) NULL);
  2222. X    i = (i == -1) ^ (match == 1);
  2223. X    free_temp(t1);
  2224. X    if (tree->type != Node_regex) {
  2225. X        free(rp->buffer);
  2226. X        free(rp->fastmap);
  2227. X        free((char *) rp);
  2228. X    }
  2229. X    return tmp_number((AWKNUM) i);
  2230. X}
  2231. END_OF_FILE
  2232.   if test 29550 -ne `wc -c <'./eval.c'`; then
  2233.     echo shar: \"'./eval.c'\" unpacked with wrong size!
  2234.   fi
  2235.   # end of './eval.c'
  2236. fi
  2237. if test -f './missing.d/gcvt.c' -a "${1}" != "-c" ; then 
  2238.   echo shar: Will not clobber existing file \"'./missing.d/gcvt.c'\"
  2239. else
  2240.   echo shar: Extracting \"'./missing.d/gcvt.c'\" \(129 characters\)
  2241.   sed "s/^X//" >'./missing.d/gcvt.c' <<'END_OF_FILE'
  2242. Xchar    *
  2243. Xgcvt(value, digits, buff)
  2244. Xdouble    value;
  2245. Xint    digits;
  2246. Xchar    *buff;
  2247. X{
  2248. X    sprintf(buff, "%*g", digits, value);
  2249. X    return (buff);
  2250. X}
  2251. END_OF_FILE
  2252.   if test 129 -ne `wc -c <'./missing.d/gcvt.c'`; then
  2253.     echo shar: \"'./missing.d/gcvt.c'\" unpacked with wrong size!
  2254.   fi
  2255.   # end of './missing.d/gcvt.c'
  2256. fi
  2257. echo shar: End of archive 12 \(of 16\).
  2258. cp /dev/null ark12isdone
  2259. MISSING=""
  2260. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
  2261.     if test ! -f ark${I}isdone ; then
  2262.     MISSING="${MISSING} ${I}"
  2263.     fi
  2264. done
  2265. if test "${MISSING}" = "" ; then
  2266.     echo You have unpacked all 16 archives.
  2267.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2268. else
  2269.     echo You still must unpack the following archives:
  2270.     echo "        " ${MISSING}
  2271. fi
  2272. exit 0
  2273. exit 0 # Just in case...
  2274.